home *** CD-ROM | disk | FTP | other *** search
- /* Black and white offscreen bitmaps.
- 94/01/11 aih removed requirement that port can't be a color port
- 94/01/02 aih added draw call-back field
- 93/12/20 aih added bounds field
- 93/12/05 aih created */
-
- #include <limits.h>
- #include "OffscreenLib.h"
- #include "MemoryLib.h"
- #include "RectangleLib.h"
-
- /* true if a valid offscreen handle */
- Boolean OffscreenValid(OffscreenHandle offscreen)
- {
- if (! HandleValidSize(offscreen, sizeof(OffscreenType))) return(false);
- if (! (**offscreen).draw) return(false);
- if (! (**offscreen).base) return(false);
- if (*(**offscreen).base && ! HandleValid((**offscreen).base)) return(false);
- return(true);
- }
-
- /* create a new offscreen bitmap */
- OffscreenHandle OffscreenBegin(GrafPtr port, OffscreenDrawType draw, void *data)
- {
- volatile OffscreenHandle offscreen = NULL;
- void *tmp = NULL;
-
- require(port != NULL);
- require(draw != NULL);
- TRY {
- offscreen = HandleBeginClear(sizeof(OffscreenType));
- (**offscreen).port = port;
- tmp = HandleBegin(0); EmptyHandle(tmp); HPurge(tmp);
- (**offscreen).base = tmp;
- (**offscreen).draw = draw;
- (**offscreen).data = data;
- (**offscreen).bounds = port->portRect;
- tmp = NewRgn(); FailNIL(tmp); (**offscreen).mask = tmp;
- tmp = NewRgn(); FailNIL(tmp); (**offscreen).clip = tmp;
- tmp = NewRgn(); FailNIL(tmp); (**offscreen).vis = tmp;
- } CATCH {
- OffscreenEnd(offscreen);
- } ENDTRY;
- ensure(OffscreenValid(offscreen));
- ensure(OffscreenPurged(offscreen));
- return(offscreen);
- }
-
- /* dispose of the offscreen bitmap */
- void OffscreenEnd(OffscreenHandle offscreen)
- {
- if (offscreen) {
- require(! (**offscreen).drawing);
- if ((**offscreen).mask) DisposeRgn((**offscreen).mask);
- if ((**offscreen).clip) DisposeRgn((**offscreen).clip);
- if ((**offscreen).vis) DisposeRgn((**offscreen).vis);
- if ((**offscreen).base) DisposeHandle((**offscreen).base);
- HandleEnd(offscreen);
- }
- }
-
- /* return the bounding rectangle of the offscreen bitmap */
- void OffscreenBounds(OffscreenHandle offscreen, Rect *bounds)
- {
- require(OffscreenValid(offscreen));
- *bounds = (**offscreen).bounds;
- ensure(RectValid(bounds));
- }
-
- /* set the bounding rectangle of the offscreen bitmap; this can be any portion
- of the offscreen bitmap's port */
- void OffscreenBoundsSet(OffscreenHandle offscreen, const Rect *bounds)
- {
- require(OffscreenValid(offscreen));
- require(RectValid(bounds));
- (**offscreen).bounds = *bounds;
- if (! OffscreenPurged(offscreen))
- OffscreenPurge(offscreen);
- ensure(OffscreenPurged(offscreen));
- }
-
- /* set flag indicating that the offscreen bitmap must be reimaged */
- void OffscreenChange(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- (**offscreen).changed = true;
- }
-
- /* purge the offscreen bitmap */
- void OffscreenPurge(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- require(! (**offscreen).srcbits.baseAddr);
- EmptyHandle((**offscreen).base);
- ensure(OffscreenPurged(offscreen));
- }
-
- /* true if the offscreen bitmap has been purged */
- Boolean OffscreenPurged(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- return(! *(**offscreen).base);
- }
-
- /* true if currently drawing into the offscreen bitmap */
- Boolean OffscreenDrawing(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- return((**offscreen).drawing);
- }
-
- /* return the offscreen bitmap's port */
- GrafPtr OffscreenPort(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- return((**offscreen).port);
- }
-
- /* lock the handle to the base address of the offscreen bitmap */
- static void OffscreenLockBase(OffscreenHandle offscreen)
- {
- (void) HandleLock((**offscreen).base);
- (**offscreen).srcbits.baseAddr = *(**offscreen).base;
- }
-
- /* unlock the handle to the base address of the offscreen bitmap */
- static void OffscreenUnlockBase(OffscreenHandle offscreen)
- {
- HandleUnlock((**offscreen).base);
- (**offscreen).srcbits.baseAddr = NULL;
- }
-
- /* lock the handle to the offscreen structure */
- static void OffscreenLock(OffscreenHandle offscreen)
- {
- (void) HandleLock(offscreen);
- }
-
- /* unlock the handle to the offscreen structure */
- static void OffscreenUnlock(OffscreenHandle offscreen)
- {
- HandleUnlock(offscreen);
- }
-
- /* draw the offscreen bitmap into the port */
- void OffscreenDrawBitMap(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- require(! OffscreenPurged(offscreen));
- require(! (**offscreen).drawing);
-
- /* calculate mask region */
- CopyRgn((**offscreen).port->clipRgn, (**offscreen).mask);
- SectRgn((**offscreen).port->visRgn, (**offscreen).mask, (**offscreen).mask);
-
- /* copy destination bits bounds rect in case port was moved */
- (**offscreen).dstbits = (**offscreen).port->portBits;
-
- /* draw the bit map */
- OffscreenLock(offscreen);
- OffscreenLockBase(offscreen);
- CopyBits(&(**offscreen).srcbits,
- &(**offscreen).dstbits,
- &(**offscreen).bounds,
- &(**offscreen).bounds,
- srcCopy, (**offscreen).mask);
- OffscreenUnlockBase(offscreen);
- OffscreenUnlock(offscreen);
- SetEmptyRgn((**offscreen).mask);
-
- ensure(OffscreenValid(offscreen));
- }
-
- /* call the application supplied draw procedure to draw the image, whether
- to the offscreen bitmap or to the on-screen bitmap */
- void OffscreenDrawProcedure(OffscreenHandle offscreen)
- {
- require(OffscreenValid(offscreen));
- (**offscreen).draw(offscreen, (**offscreen).data);
- }
-
- /* If the offscreen bitmap's image has changed or if the bitmap was purged,
- then reimage the bitmap and then draw the bitmap to the screen. If there's
- insufficient memory to allocate the bitmap then just draw to the screen. */
- void OffscreenDraw(OffscreenHandle offscreen)
- {
- volatile Boolean failed = false;
-
- require(OffscreenValid(offscreen));
- TRY {
- if (! failed) {
- if ((**offscreen).changed || OffscreenPurged(offscreen)) {
- OffscreenBeginDrawing(offscreen);
- OffscreenDrawProcedure(offscreen);
- OffscreenEndDrawing(offscreen);
- (**offscreen).changed = false;
- }
- OffscreenDrawBitMap(offscreen);
- }
- else
- OffscreenDrawProcedure(offscreen);
- } CATCH {
- if (OffscreenDrawing(offscreen))
- OffscreenEndDrawing(offscreen);
- if (! failed && FailReason() == memFullErr) {
- failed = true;
- RETRY;
- }
- } ENDTRY;
- ensure(OffscreenValid(offscreen));
- }
-
- /* Reassign the offscreen fields and reallocate the base address
- for the offscreen bitmap if it was purged or if its size changed.
- This must be called before beginning to draw the offscreen bitmap. */
- static void OffscreenReallocate(OffscreenHandle offscreen)
- {
- size_t n = 0;
- Rect bounds;
-
- require(OffscreenValid(offscreen));
- require(! (**offscreen).drawing);
- require(! (**offscreen).srcbits.baseAddr);
- bounds = (**offscreen).bounds;
- (**offscreen).dstbits = (**offscreen).port->portBits;
- (**offscreen).srcbits.bounds = bounds;
- (**offscreen).srcbits.rowBytes = ((RectWidth(&bounds) + 15) / 16) * 2;
- n = RectHeight(&bounds) * (**offscreen).srcbits.rowBytes;
- if (n != GetHandleSize((**offscreen).base)) {
- EmptyHandle((**offscreen).base);
- FailMemError();
- }
- if (! *(**offscreen).base) {
- MemCheck(n);
- ReallocateHandle((**offscreen).base, n);
- FailMemError();
- (void) HandlePurge((**offscreen).base);
- }
- ensure(! OffscreenPurged(offscreen));
- }
-
- /* Initialize the offscreen's port so that all subsequent drawing into
- it will go to the offscreen bitmap. The clip and visible regions
- are set to the maximum size. This function must be balanced with a
- call to OffscreenEndDrawing. Between the two calls, the size,
- position, and visibility of the port should not be changed. */
- void OffscreenBeginDrawing(OffscreenHandle offscreen)
- {
- Rect wide = { SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX };
- GrafPtr port = NULL;
-
- require(OffscreenValid(offscreen));
- require(! (**offscreen).drawing);
- OffscreenReallocate(offscreen);
- OffscreenLockBase(offscreen);
- OffscreenLock(offscreen);
- GetPort(&port);
- SetPort((**offscreen).port);
- CopyRgn((**offscreen).port->clipRgn, (**offscreen).clip);
- CopyRgn((**offscreen).port->visRgn, (**offscreen).vis);
- RectRgn((**offscreen).port->clipRgn, &wide);
- RectRgn((**offscreen).port->visRgn, &wide);
- SetPortBits(&(**offscreen).srcbits);
- SetPort(port);
- OffscreenUnlock(offscreen);
- (**offscreen).drawing = true;
- ensure(OffscreenValid(offscreen));
- ensure((**offscreen).drawing);
- }
-
- /* Restore the offscreen port's bitmap to its original setting. */
- void OffscreenEndDrawing(OffscreenHandle offscreen)
- {
- GrafPtr port = NULL;
-
- require(OffscreenValid(offscreen));
- require((**offscreen).drawing);
- OffscreenUnlockBase(offscreen);
- OffscreenLock(offscreen);
- GetPort(&port);
- SetPort((**offscreen).port);
- CopyRgn((**offscreen).clip, (**offscreen).port->clipRgn);
- CopyRgn((**offscreen).vis, (**offscreen).port->visRgn);
- SetEmptyRgn((**offscreen).clip);
- SetEmptyRgn((**offscreen).vis);
- SetPortBits(&(**offscreen).dstbits);
- SetPort(port);
- OffscreenUnlock(offscreen);
- (**offscreen).drawing = false;
- ensure(OffscreenValid(offscreen));
- ensure(! (**offscreen).drawing);
- }
-